﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace HML.Design
{
    /// <summary>
    /// TabControlPlus的设计模式行为
    /// </summary>
    internal class TabControlPlusDesigner : ParentControlDesigner
    {
        #region 字段

        private bool tabControlSelected;//TabControlPlus在设计器是否已选中
        private bool forwardOnDrag;//是否在拖动控件
        private bool addingOnInitialize;//通知 System.ComponentModel.Design.IComponentChangeService 此组件即将被更改

        private DesignerVerbCollection verbs;//智能标记
        private DesignerVerb removeVerb;//添加选项卡
        private DesignerVerb addVerb;//移除选项卡

        #endregion

        #region 重写属性

        /// <summary>
        /// 获取一个值，该值指示选择的控件是否重新设置为父级。
        /// </summary>
        protected override bool AllowControlLasso
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 获取一个值，该值指示在拖动操作期间 System.Windows.Forms.Design.ControlDesigner 是否允许按对齐线对齐。
        /// </summary>
        public override bool ParticipatesWithSnapLines
        {
            get
            {
                if (!this.forwardOnDrag)
                {
                    return false;
                }
                TabPagePlusDesigner selectedTabPageDesigner = this.GetSelectedTabPageDesigner();
                if (selectedTabPageDesigner != null)
                {
                    return selectedTabPageDesigner.ParticipatesWithSnapLines;
                }
                return true;
            }
        }

        /// <summary>
        /// 智能标记
        /// </summary>
        public override DesignerVerbCollection Verbs
        {
            get
            {
                if (this.verbs == null)
                {
                    this.addVerb = new DesignerVerb("添加选项卡", new EventHandler(this.OnAdd));
                    this.removeVerb = new DesignerVerb("移除选项卡", new EventHandler(this.OnRemove));

                    this.verbs = new DesignerVerbCollection();
                    this.verbs.Add(this.addVerb);
                    this.verbs.Add(this.removeVerb);
                }
                if (this.Control != null)
                {
                    this.removeVerb.Enabled = this.Control.Controls.Count > 0;
                }
                return this.verbs;
            }
        }

        #endregion

        #region 重写方法

        /// <summary>
        /// 指示指定的控件是否可以是由此设计器管理的控件的子级。
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        public override bool CanParent(Control control)
        {
            if (control is TabPagePlus)
            {
                return !this.Control.Contains(control);
            }
            return false;
        }

        /// <summary>
        /// 指示该控件是否应处理在指定点单击鼠标的操作。
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        protected override bool GetHitTest(Point point)
        {
            if (this.tabControlSelected == false)
            {
                return false;
            }

            TabControlPlus tabControl = (TabControlPlus)this.Control;

            Point pt = this.Control.PointToClient(point);
            if (tabControl.JudgePointInItem(pt) || tabControl.JudgePointNavigationButton(pt))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 视图设计器创建TabControlPlus控件
        /// </summary>
        /// <param name="tool"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="hasLocation"></param>
        /// <param name="hasSize"></param>
        /// <returns></returns>
        protected override IComponent[] CreateToolCore(ToolboxItem tool, int x, int y, int width, int height, bool hasLocation, bool hasSize)
        {
            TabControlPlus tabControl = (TabControlPlus)this.Control;
            if (tabControl.SelectedTab == null)
            {
                throw new ArgumentException(String.Format("不能添加\'{0}\'到TabControlPlus。只有TabPagePlus可以直接添加到TabControlPlus中。", tool.DisplayName));
            }

            IDesignerHost designerHost = (IDesignerHost)this.GetService(typeof(IDesignerHost));
            if (designerHost != null)
            {
                ParentControlDesigner.InvokeCreateTool((ParentControlDesigner)designerHost.GetDesigner((IComponent)tabControl.SelectedTab), tool);
            }
            return (IComponent[])null;
        }

        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            this.AutoResizeHandles = true;

            ISelectionService selectionService = (ISelectionService)this.GetService(typeof(ISelectionService));
            if (selectionService != null)
            {
                selectionService.SelectionChanged += new EventHandler(this.OnSelectionChanged);
            }

            IComponentChangeService componentChangeService = (IComponentChangeService)this.GetService(typeof(IComponentChangeService));
            if (componentChangeService != null)
            {
                componentChangeService.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
            }

        }

        /// <summary>
        /// 创建时添加默认选项
        /// </summary>
        /// <param name="defaultValues"></param>
        public override void InitializeNewComponent(System.Collections.IDictionary defaultValues)
        {
            base.InitializeNewComponent(defaultValues);

            try
            {
                this.addingOnInitialize = true;
                this.OnAdd((object)this, EventArgs.Empty);
                this.OnAdd((object)this, EventArgs.Empty);
            }
            finally
            {
                this.addingOnInitialize = false;
            }
            MemberDescriptor member = (MemberDescriptor)TypeDescriptor.GetProperties((object)this.Component)["Controls"];
            this.RaiseComponentChanging(member);
            this.RaiseComponentChanged(member, (object)null, (object)null);

            TabControlPlus tabControl = (TabControlPlus)this.Component;
            if (tabControl != null)
            {
                if (tabControl.TabCount > 0)
                {
                    tabControl.SelectedIndex = 0;
                }
                else
                {
                    tabControl.SelectedIndex = -1;
                }
            }
        }

        /// <summary>
        /// 绘制边框
        /// </summary>
        /// <param name="pe"></param>
        protected override void OnPaintAdornments(PaintEventArgs pe)
        {
            TabControlPlus tabControl = (TabControlPlus)this.Control;
            if (tabControl == null || tabControl.Visible == false || tabControl.TabCount > 0)
                return;

            Pen borderPen = new Pen((double)this.Control.BackColor.GetBrightness() < 0.5 ? ControlPaint.Light(this.Control.BackColor) : ControlPaint.Dark(this.Control.BackColor)) { DashStyle = DashStyle.Dash };
            Rectangle clientRectangle = this.Control.ClientRectangle;
            --clientRectangle.Width;
            --clientRectangle.Height;
            pe.Graphics.DrawRectangle(borderPen, clientRectangle);
            borderPen.Dispose();

            base.OnPaintAdornments(pe);
        }

        /// <summary>
        /// 右键菜单
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            int msg = m.Msg;
            switch (msg)
            {
                case 123:
                    int x = this.SignedLOWORD((int)(long)m.LParam);
                    int y = this.SignedHIWORD((int)(long)m.LParam);
                    if (x == -1 && y == -1)
                    {
                        Point position = Cursor.Position;
                        x = position.X;
                        y = position.Y;
                    }
                    this.OnContextMenu(x, y);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }

        #endregion

        #region 方法

        /// <summary>
        /// 组件更改后事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnComponentChanged(object sender, ComponentChangedEventArgs e)
        {
            // 修改智能标记的启用状态
            if (this.removeVerb != null)
            {
                this.removeVerb.Enabled = this.Control.Controls.Count > 0;
            }
        }

        /// <summary>
        /// 视图设计器选中控件更改事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSelectionChanged(object sender, EventArgs e)
        {
            this.tabControlSelected = false;
            ISelectionService selectionService = (ISelectionService)this.GetService(typeof(ISelectionService));
            if (selectionService == null)
            {
                return;
            }

            System.Collections.ICollection selectedComponents = selectionService.GetSelectedComponents();//获取设计器所有选中的控件
            TabControlPlus parent = (TabControlPlus)this.Component;
            foreach (object comp in (System.Collections.IEnumerable)selectedComponents)
            {
                if (comp == parent)
                {
                    this.tabControlSelected = true;
                }
                TabPagePlus tabPageOfComponent = TabControlPlusDesigner.GetTabPageOfComponent(parent, comp);//获取视图设计器TabControlPlus选中的TabPagePlus
                if (tabPageOfComponent != null && tabPageOfComponent.Parent == parent)
                {
                    this.tabControlSelected = false;
                    parent.SelectedTab = tabPageOfComponent;

                    tabPageOfComponent.Refresh();
                    break;
                }
            }
        }

        /// <summary>
        /// 添加一个选项卡事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eevent"></param>
        private void OnAdd(object sender, EventArgs eevent)
        {
            IDesignerHost designerHost1 = (IDesignerHost)this.GetService(typeof(IDesignerHost));
            if (designerHost1 == null)
            {
                return;
            }

            DesignerTransaction designerTransaction = (DesignerTransaction)null;//用于设计器撤销、重做的历史记录功能
            try
            {
                TabControlPlus tabControl = (TabControlPlus)this.Component;

                try
                {
                    designerTransaction = designerHost1.CreateTransaction(String.Format("添加选项卡到 \"{0}\"", tabControl.Site.Name));
                }
                catch (CheckoutException ex)
                {
                    if (ex == CheckoutException.Canceled)
                    {
                        return;
                    }
                    throw ex;
                }

                MemberDescriptor member = (MemberDescriptor)TypeDescriptor.GetProperties((object)tabControl)["Controls"];
                TabPagePlus tabPage = (TabPagePlus)designerHost1.CreateComponent(typeof(TabPagePlus));
                if (this.addingOnInitialize == false)
                {
                    this.RaiseComponentChanging(member);
                }
                tabPage.Padding = new Padding(3);
                string str = (string)null;
                PropertyDescriptor propertyDescriptor1 = TypeDescriptor.GetProperties((object)tabPage)["Name"];
                if (propertyDescriptor1 != null && propertyDescriptor1.PropertyType == typeof(string))
                {
                    str = (string)propertyDescriptor1.GetValue((object)tabPage);
                }
                if (str != null)
                {
                    PropertyDescriptor propertyDescriptor2 = TypeDescriptor.GetProperties((object)tabPage)["Text"];
                    if (propertyDescriptor2 != null)
                    {
                        propertyDescriptor2.SetValue((object)tabPage, (object)str);
                    }
                }

                tabControl.Controls.Add((Control)tabPage);
                tabControl.SelectedIndex = tabControl.TabCount - 1;
                this.RaiseComponentChanged(member, (object)null, (object)null);
            }
            finally
            {
                if (designerTransaction != null)
                {
                    designerTransaction.Commit();
                }
            }
        }

        /// <summary>
        /// 移除一个选项卡事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eevent"></param>
        private void OnRemove(object sender, EventArgs eevent)
        {
            IDesignerHost designerHost1 = (IDesignerHost)this.GetService(typeof(IDesignerHost));
            if (designerHost1 == null)
            {
                return;
            }

            TabControlPlus tabControl = (TabControlPlus)this.Component;
            if (tabControl == null || tabControl.TabPages.Count == 0)
            {
                return;
            }

            DesignerTransaction designerTransaction = (DesignerTransaction)null;//用于设计器撤销、重做的历史记录功能
            try
            {
                MemberDescriptor member = (MemberDescriptor)TypeDescriptor.GetProperties((object)this.Component)["Controls"];
                TabPagePlus selectedTab = tabControl.SelectedTab;

                try
                {
                    designerTransaction = designerHost1.CreateTransaction(String.Format("添加选项卡 \"{0}\" 来自 \"{1}\" ", selectedTab.Name, tabControl.Site.Name));
                    this.RaiseComponentChanging(member);
                }
                catch (CheckoutException ex)
                {
                    if (ex == CheckoutException.Canceled)
                    {
                        return;
                    }
                    throw ex;
                }

                designerHost1.DestroyComponent((IComponent)selectedTab);
                this.RaiseComponentChanged(member, (object)null, (object)null);
            }
            finally
            {
                if (designerTransaction != null)
                {
                    designerTransaction.Commit();
                }
            }
        }

        /// <summary>
        /// 获取视图设计器TabControlPlus选中的TabPagePlus
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="comp"></param>
        /// <returns></returns>
        internal static TabPagePlus GetTabPageOfComponent(TabControlPlus parent, object comp)
        {
            if (!(comp is Control))
            {
                return (TabPagePlus)null;
            }
            for (Control control = (Control)comp; control != null; control = control.Parent)
            {
                TabPagePlus tabPage = control as TabPagePlus;
                if (tabPage != null && tabPage.Parent == parent)
                {
                    return tabPage;
                }
            }
            return (TabPagePlus)null;
        }

        /// <summary>
        /// 获取选中的TabPagePlus的TabPagePlusDesigner设计器
        /// </summary>
        /// <returns></returns>
        private TabPagePlusDesigner GetSelectedTabPageDesigner()
        {
            TabPagePlusDesigner tabPageDesigner = (TabPagePlusDesigner)null;
            TabPagePlus selectedTab = ((TabControlPlus)this.Component).SelectedTab;
            if (selectedTab != null)
            {
                IDesignerHost designerHost = (IDesignerHost)this.GetService(typeof(IDesignerHost));
                if (designerHost != null)
                    tabPageDesigner = designerHost.GetDesigner((IComponent)selectedTab) as TabPagePlusDesigner;
            }
            return tabPageDesigner;
        }

        private int SignedLOWORD(int n)
        {
            return (int)(short)(n & (int)ushort.MaxValue) << 16 >> 16;
        }

        private int SignedHIWORD(int n)
        {
            return (int)(short)(n >> 16 & (int)ushort.MaxValue) << 16 >> 16;
        }

        #endregion

        #region 拖载

        protected override void OnDragEnter(DragEventArgs de)
        {
            this.forwardOnDrag = true;
            if (this.forwardOnDrag)
            {
                TabPagePlusDesigner selectedTabPageDesigner = this.GetSelectedTabPageDesigner();
                if (selectedTabPageDesigner == null)
                {
                    return;
                }
                selectedTabPageDesigner.OnDragEnterInternal(de);//通知TabPagePlusDesigner拖载操作
            }
            else
            {
                base.OnDragEnter(de);
            }
        }

        protected override void OnDragDrop(DragEventArgs de)
        {
            if (this.forwardOnDrag)
            {
                TabPagePlusDesigner selectedTabPageDesigner = this.GetSelectedTabPageDesigner();
                if (selectedTabPageDesigner != null)
                {
                    selectedTabPageDesigner.OnDragDropInternal(de);//通知TabPagePlusDesigner拖载操作
                }
            }
            else
            {
                base.OnDragDrop(de);
            }
            this.forwardOnDrag = false;
        }

        protected override void OnDragLeave(EventArgs e)
        {
            if (this.forwardOnDrag)
            {
                TabPagePlusDesigner selectedTabPageDesigner = this.GetSelectedTabPageDesigner();
                if (selectedTabPageDesigner != null)
                {
                    selectedTabPageDesigner.OnDragLeaveInternal(e);//通知TabPagePlusDesigner拖载操作
                }
            }
            else
            {
                base.OnDragLeave(e);
            }
            this.forwardOnDrag = false;
        }

        protected override void OnDragOver(DragEventArgs de)
        {
            if (this.forwardOnDrag)
            {
                TabControlPlus tabControl = (TabControlPlus)this.Control;
                if (tabControl.GetBodyDisplayRectangle().Contains(this.Control.PointToClient(new Point(de.X, de.Y))) == false)
                {
                    de.Effect = DragDropEffects.None;
                }
                else
                {
                    TabPagePlusDesigner selectedTabPageDesigner = this.GetSelectedTabPageDesigner();
                    if (selectedTabPageDesigner == null)
                    {
                        return;
                    }
                    selectedTabPageDesigner.OnDragOverInternal(de);//通知TabPagePlusDesigner拖载操作
                }
            }
            else
            {
                base.OnDragOver(de);
            }
        }

        protected override void OnGiveFeedback(GiveFeedbackEventArgs e)
        {
            if (this.forwardOnDrag)//通知TabPagePlusDesigner拖载操作
            {
                TabPagePlusDesigner selectedTabPageDesigner = this.GetSelectedTabPageDesigner();
                if (selectedTabPageDesigner == null)
                {
                    return;
                }
                selectedTabPageDesigner.OnGiveFeedbackInternal(e);
            }
            else
            {
                base.OnGiveFeedback(e);
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                ISelectionService selectionService = (ISelectionService)this.GetService(typeof(ISelectionService));
                if (selectionService != null)
                {
                    selectionService.SelectionChanged -= new EventHandler(this.OnSelectionChanged);
                }
                IComponentChangeService componentChangeService = (IComponentChangeService)this.GetService(typeof(IComponentChangeService));
                if (componentChangeService != null)
                {
                    componentChangeService.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged);
                }
            }
            base.Dispose(disposing);
        }

        #endregion

    }

}
